#include "HSpline.h"

void HSpline::SetTension( float c )
{
	m_tension = c;
}


float HSpline::Getlength()
{
	float sum = 0;
	int size = (int)m_Vector6s.size();
	for (int i=0;i < size;i++)
	{
		sum += m_Vector6s[i].pos.distance(m_Vector6s[(i+1)%size].pos);
	}
	return sum;
}

void HSpline::GetInfoByPercent( float num, Ogre::Vector3& pos, Ogre::Vector3 &ori )
{
	float len = Getlength();
	float poslen = len*num;
	poslen = poslen>len?len:poslen;
	for (int i=0;i<(int)m_Segments.size();i++)
	{
		if (poslen-m_Segments[i].GetLength() > 0)
			poslen-=m_Segments[i].GetLength();
		else
		{
			pos = m_Segments[i].GetPosByPercent(poslen/m_Segments[i].GetLength());
			ori = m_Segments[i].GetOriByPercent(poslen/m_Segments[i].GetLength());
			break;
		}
	}
}

void HSpline::BuildSegments()
{
	ControlPoints &refpoints = *m_refpoints;
	int size = (int)refpoints.size();
	for (int i=0;i < size;i++)
		refpoints[i].Update();
	m_Segs.clear();
	for (int i=0;i < size;i++)
	{
		m_Segs.push_back(Seg4V(Vector6(refpoints[i].m_pos, refpoints[i].m_ori),
			Vector6(refpoints[(i+1)%size].m_pos, refpoints[(i+1)%size].m_ori),
			Vector6(refpoints[(i+2)%size].m_pos, refpoints[(i+2)%size].m_ori),
			Vector6(refpoints[(i+3)%size].m_pos, refpoints[(i+3)%size].m_ori)));
	}
	m_Vector6s.clear();
	for (int pot=0;pot < (int)m_Segs.size();pot++)
	{
		Seg4V &bsseg = m_Segs[pot];
		for (int i=0;i < CUT_NUM;i++)
		{
			Ogre::Vector3 pos = CalcHSplineCurve(bsseg.p1.pos, bsseg.p2.pos, bsseg.p3.pos, bsseg.p4.pos,
				i / CUT_NUM, m_tension);
			Ogre::Vector3 ori = CalcHSplineCurve(bsseg.p1.ori, bsseg.p2.ori, bsseg.p3.ori, bsseg.p4.ori,
				i / CUT_NUM, m_tension);
			m_Vector6s.push_back(Vector6(pos, ori));
		}
	}
	Seg4Vs().swap(m_Segs); // release BSSegs space
	m_Segments.clear();
	int vectorSize = (int)m_Vector6s.size();
	for (int i=0;i<vectorSize;i++)
		m_Segments.push_back(PointSegment(m_Vector6s[i], m_Vector6s[(i+1)%vectorSize]));
}

